<template>
  <div class="data-governance-container">
    <!-- 顶部标题 -->
    <div class="header">
      <h2>数据治理</h2>
      <div class="desc">监控和管理数据质量、脱敏规则、权限配置和血缘关系</div>
    </div>
    <el-row :gutter="20" class="top-panels">
      <!-- 数据质量监控面板 -->
      <el-col :span="12">
        <el-card class="panel-card">
          <div class="panel-title">
            <i class="el-icon-data-analysis"></i> 数据质量监控
            <el-button size="mini" @click="showRuleDialog = true" style="float:right">指标配置</el-button>
          </div>
          <div class="quality-score">
            <div class="score">{{ qualityScore }}</div>
            <div class="score-label">质量评分</div>
            <div class="metrics">
              <div>完整性 <span class="metric-value">{{ rules.integrity.value }}%</span></div>
              <div>准确性 <span class="metric-value">{{ rules.accuracy.value }}%</span></div>
              <div>及时性 <span class="metric-value">{{ rules.timeliness.value }}%</span></div>
            </div>
          </div>
        </el-card>
      </el-col>
      <!-- 字段脱敏管理 -->
      <el-col :span="12">
        <el-card class="panel-card">
          <div class="panel-title">
            <i class="el-icon-lock"></i> 数据脱敏管理
            <el-button size="mini" type="primary" @click="showDesensDialog = true" style="float:right">添加规则</el-button>
          </div>
          <div class="desens-summary">
            <el-progress :percentage="desensSummary.donePercent" status="success" style="width: 60%"/>
            <span>已脱敏字段 {{ desensSummary.doneCount }}</span>
            <span style="margin-left: 20px">待脱敏字段 {{ desensSummary.todoCount }}</span>
          </div>
        </el-card>
      </el-col>
    </el-row>
    <el-row :gutter="20" class="mid-panels">
      <!-- 权限管理 -->
      <el-col :span="12">
        <el-card class="panel-card">
          <div class="panel-title">
            <i class="el-icon-s-check"></i> 权限管理
            <el-button size="mini" @click="showRbacDialog = true" style="float:right">配置权限</el-button>
          </div>
          <el-table :data="rbacRoles" border size="mini" style="margin-top: 10px">
            <el-table-column prop="role" label="角色" width="120"/>
            <el-table-column prop="desc" label="权限描述"/>
            <el-table-column label="状态" width="80">
              <template slot-scope="scope">
                <el-tag :type="scope.row.status === '正常' ? 'success' : 'warning'">{{ scope.row.status }}</el-tag>
              </template>
            </el-table-column>
          </el-table>
        </el-card>
      </el-col>
      <!-- 数据血缘追溯 -->
      <el-col :span="12">
        <el-card class="panel-card">
          <div class="panel-title">
            <i class="el-icon-share"></i> 数据血缘追溯
            <el-button size="mini" @click="showLineageDialog = true" style="float:right">查看详情</el-button>
          </div>
          <div class="lineage-search">
            <el-input v-model="lineageField" placeholder="输入字段名称查询..." size="small" style="width: 70%" @keyup.enter.native="drawLineage"/>
            <el-button size="small" @click="drawLineage">查询</el-button>
          </div>
          <div v-if="lineageSVG" class="lineage-svg-preview" v-html="lineageSVG"></div>
        </el-card>
      </el-col>
    </el-row>
    <!-- 数据质量趋势 -->
    <el-card class="panel-card" style="margin-top: 20px">
      <div class="panel-title"><i class="el-icon-trend-charts"></i> 数据质量趋势</div>
      <div ref="qualityChart" style="height: 260px; width: 100%"></div>
    </el-card>

    <!-- 指标配置弹窗 -->
    <el-dialog title="监控规则配置" :visible.sync="showRuleDialog" width="500px">
      <el-form :model="rules" label-width="80px">
        <el-form-item label="完整性">
          <el-input v-model.number="rules.integrity.threshold" placeholder="必填字段缺失率阈值(%)" type="number" min="0" max="100"/>
        </el-form-item>
        <el-form-item label="准确性">
          <el-input v-model.number="rules.accuracy.threshold" placeholder="传感器数据偏差阈值(%)" type="number" min="0" max="100"/>
        </el-form-item>
        <el-form-item label="及时性">
          <el-input v-model.number="rules.timeliness.threshold" placeholder="数据延迟阈值(秒)" type="number" min="0"/>
        </el-form-item>
        <el-form-item label="异常预警">
          <el-checkbox v-model="rules.alert.enable">启用</el-checkbox>
          <el-input v-if="rules.alert.enable" v-model="rules.alert.notify" placeholder="邮件/短信通知人，逗号分隔" style="margin-top: 10px"/>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="showRuleDialog = false">取 消</el-button>
        <el-button type="primary" @click="saveRules">保 存</el-button>
      </div>
    </el-dialog>

    <!-- 字段脱敏弹窗 -->
    <el-dialog title="字段脱敏配置" :visible.sync="showDesensDialog" width="500px">
      <el-form :model="desensConfig" label-width="100px">
        <el-form-item label="表名">
          <el-select v-model="desensConfig.table" placeholder="请选择表">
            <el-option label="客户信息表" value="customer"/>
          </el-select>
        </el-form-item>
        <el-form-item label="字段">
          <el-select v-model="desensConfig.field" placeholder="请选择字段">
            <el-option label="身份证号" value="idCard"/>
          </el-select>
        </el-form-item>
        <el-form-item label="掩码规则">
          <el-input v-model="desensConfig.maskRule" placeholder="如******1234"/>
        </el-form-item>
        <el-form-item label="启用">
          <el-switch v-model="desensConfig.enable"/>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="showDesensDialog = false">取 消</el-button>
        <el-button type="primary" @click="saveDesens">保 存</el-button>
      </div>
    </el-dialog>

    <!-- 权限配置弹窗 -->
    <el-dialog title="RBAC权限配置" :visible.sync="showRbacDialog" width="500px">
      <el-form :model="rbacConfig" label-width="120px">
        <el-form-item label="工艺工程师">
          <el-checkbox v-model="rbacConfig.engineer">设备数据只读</el-checkbox>
        </el-form-item>
        <el-form-item label="管理员">
          <el-checkbox v-model="rbacConfig.admin">全量数据访问</el-checkbox>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="showRbacDialog = false">取 消</el-button>
        <el-button type="primary" @click="saveRbac">保 存</el-button>
      </div>
    </el-dialog>

    <!-- 数据血缘追溯弹窗 -->
    <el-dialog title="数据血缘追溯" :visible.sync="showLineageDialog" width="600px">
      <el-form label-width="100px">
        <el-form-item label="字段名">
          <el-input v-model="lineageFieldDialog" placeholder="如主轴温度"/>
        </el-form-item>
      </el-form>
      <div v-if="lineageSVGDialog" v-html="lineageSVGDialog" class="lineage-svg-preview" style="margin-bottom: 10px"></div>
      <el-button type="primary" @click="exportSVG">导出SVG报告</el-button>
      <div slot="footer" class="dialog-footer">
        <el-button @click="showLineageDialog = false">关 闭</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import echarts from 'echarts'

const RULES_KEY = 'dg_rules'
const DESENS_KEY = 'dg_desens'
const RBAC_KEY = 'dg_rbac'

export default {
  name: 'DataGovernance',
  data() {
    return {
      showRuleDialog: false,
      showDesensDialog: false,
      showRbacDialog: false,
      showLineageDialog: false,
      // 监控规则
      rules: {
        integrity: { value: 98, threshold: 5 },
        accuracy: { value: 95, threshold: 3 },
        timeliness: { value: 92, threshold: 10 },
        alert: { enable: false, notify: '' }
      },
      // 脱敏配置
      desensConfig: {
        table: 'customer',
        field: 'idCard',
        maskRule: '******1234',
        enable: true
      },
      desensSummary: {
        doneCount: 1,
        todoCount: 1,
        donePercent: 80
      },
      // 权限配置
      rbacConfig: {
        engineer: true,
        admin: true
      },
      rbacRoles: [
        { role: '管理员', desc: '全量数据访问', status: '正常' },
        { role: '工艺工程师', desc: '设备数据只读', status: '正常' },
        { role: '数据分析师', desc: '报表数据访问', status: '部分' }
      ],
      // 血缘追溯
      lineageField: '',
      lineageSVG: '',
      lineageFieldDialog: '',
      lineageSVGDialog: '',
      // 质量评分
      qualityScore: 85,
      // 质量趋势
      qualityTrend: [90, 92, 88, 91, 93, 89, 90],
      abnormalTrend: [2, 1, 3, 2, 1, 2, 1]
    }
  },
  mounted() {
    this.loadLocal()
    this.drawQualityChart()
  },
  watch: {
    showRuleDialog(val) {
      if (!val) this.loadLocal()
    },
    showDesensDialog(val) {
      if (!val) this.loadLocal()
    },
    showRbacDialog(val) {
      if (!val) this.loadLocal()
    }
  },
  methods: {
    // 本地存取
    loadLocal() {
      // 监控规则
      const rules = localStorage.getItem(RULES_KEY)
      if (rules) this.rules = JSON.parse(rules)
      // 脱敏
      const desens = localStorage.getItem(DESENS_KEY)
      if (desens) this.desensConfig = JSON.parse(desens)
      // 权限
      const rbac = localStorage.getItem(RBAC_KEY)
      if (rbac) this.rbacConfig = JSON.parse(rbac)
      // 脱敏统计
      this.desensSummary = {
        doneCount: this.desensConfig.enable ? 1 : 0,
        todoCount: this.desensConfig.enable ? 0 : 1,
        donePercent: this.desensConfig.enable ? 80 : 20
      }
    },
    saveRules() {
      localStorage.setItem(RULES_KEY, JSON.stringify(this.rules))
      this.showRuleDialog = false
      this.$message.success('保存成功')
      this.loadLocal()
    },
    saveDesens() {
      localStorage.setItem(DESENS_KEY, JSON.stringify(this.desensConfig))
      this.showDesensDialog = false
      this.$message.success('保存成功')
      this.loadLocal()
    },
    saveRbac() {
      localStorage.setItem(RBAC_KEY, JSON.stringify(this.rbacConfig))
      this.showRbacDialog = false
      this.$message.success('保存成功')
      this.loadLocal()
    },
    // 质量趋势图
    drawQualityChart() {
      this.$nextTick(() => {
        const chart = echarts.init(this.$refs.qualityChart)
        chart.setOption({
          tooltip: { trigger: 'axis' },
          legend: { data: ['质量评分', '异常次数'] },
          xAxis: { type: 'category', data: ['周一','周二','周三','周四','周五','周六','周日'] },
          yAxis: { type: 'value' },
          series: [
            { name: '质量评分', type: 'line', data: this.qualityTrend, smooth: true },
            { name: '异常次数', type: 'line', data: this.abnormalTrend, smooth: true }
          ]
        })
      })
    },
    // 血缘追溯
    drawLineage() {
      const field = this.lineageField.trim()
      if (!field) {
        this.$message.warning('请输入字段名')
        return
      }
      this.lineageSVG = this.genLineageSVG(field)
    },
    genLineageSVG(field) {
      // 简单链路：传感器采集→边缘预处理→云端存储
      const nodes = [
        { label: '传感器采集', x: 40, y: 60 },
        { label: '边缘预处理', x: 220, y: 60 },
        { label: '云端存储', x: 400, y: 60 },
        { label: field, x: 220, y: 140 }
      ]
      const arrows = [
        { from: 0, to: 1 },
        { from: 1, to: 2 },
        { from: 1, to: 3 }
      ]
      let svg = `<svg width='480' height='180' xmlns='http://www.w3.org/2000/svg'>`
      nodes.forEach((n, i) => {
        svg += `<rect x='${n.x}' y='${n.y}' width='100' height='36' rx='8' fill='#f5f7fa' stroke='#409EFF' stroke-width='2'/><text x='${n.x+50}' y='${n.y+22}' text-anchor='middle' font-size='14' fill='#333'>${n.label}</text>`
      })
      arrows.forEach(a => {
        const from = nodes[a.from], to = nodes[a.to]
        svg += `<line x1='${from.x+100}' y1='${from.y+18}' x2='${to.x}' y2='${to.y+18}' stroke='#409EFF' stroke-width='2' marker-end='url(#arrow)'/>`
      })
      svg += `<defs><marker id='arrow' markerWidth='10' markerHeight='10' refX='10' refY='5' orient='auto'><path d='M0,0 L10,5 L0,10 Z' fill='#409EFF'/></marker></defs>`
      svg += `</svg>`
      return svg
    },
    // 弹窗血缘
    exportSVG() {
      if (!this.lineageSVGDialog) {
        this.$message.warning('请先输入字段名并查询')
        return
      }
      const blob = new Blob([this.lineageSVGDialog], { type: 'image/svg+xml' })
      const url = URL.createObjectURL(blob)
      const a = document.createElement('a')
      a.href = url
      a.download = `血缘追溯_${this.lineageFieldDialog}.svg`
      a.click()
      URL.revokeObjectURL(url)
    }
  },
  watch: {
    showLineageDialog(val) {
      if (val) {
        this.lineageFieldDialog = this.lineageField
        this.lineageSVGDialog = this.lineageField ? this.genLineageSVG(this.lineageField) : ''
      }
    },
    lineageFieldDialog(val) {
      this.lineageSVGDialog = val ? this.genLineageSVG(val) : ''
    }
  }
}
</script>

<style scoped>
.data-governance-container {
  padding: 24px;
  background: #f5f7fa;
  min-height: 100vh;
}
.header {
  margin-bottom: 18px;
}
.header h2 {
  margin: 0 0 4px 0;
  font-size: 22px;
  font-weight: bold;
}
.header .desc {
  color: #888;
  font-size: 14px;
}
.top-panels, .mid-panels {
  margin-bottom: 18px;
}
.panel-card {
  border-radius: 8px;
}
.panel-title {
  font-weight: bold;
  font-size: 16px;
  margin-bottom: 8px;
}
.quality-score {
  display: flex;
  align-items: center;
  margin-top: 10px;
}
.quality-score .score {
  font-size: 38px;
  color: #409EFF;
  font-weight: bold;
  margin-right: 18px;
}
.quality-score .score-label {
  color: #888;
  margin-right: 24px;
}
.quality-score .metrics {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.metric-value {
  color: #409EFF;
  font-weight: bold;
}
.desens-summary {
  display: flex;
  align-items: center;
  margin-top: 18px;
  gap: 16px;
}
.lineage-search {
  margin: 10px 0;
  display: flex;
  align-items: center;
  gap: 8px;
}
.lineage-svg-preview {
  margin-top: 10px;
  background: #fff;
  border: 1px solid #eee;
  border-radius: 6px;
  padding: 8px;
  min-height: 80px;
  text-align: center;
}
</style>
